"""MCP客户端工具"""

import asyncio
import json
import subprocess
import time
from typing import Dict, List, Any, Optional
from contextlib import AsyncExitStack
from dataclasses import dataclass

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

from core.base_tools import BaseExternalTool, SearchResult, ExternalToolCache


class MCPGitHubTool(BaseExternalTool):
    """MCP GitHub工具客户端"""
    
    def __init__(self, cache: ExternalToolCache):
        super().__init__(cache)
        self.session: Optional[ClientSession] = None
        self.exit_stack = AsyncExitStack()
        self.server_process = None
        self.is_connected = False
        
    async def _start_mcp_server(self):
        """启动MCP GitHub服务器"""
        if self.server_process is None:
            print("🚀 [MCP GitHub客户端] 启动MCP GitHub服务器...")
            
            # 启动MCP服务器进程
            server_script_path = "/Users/dyq/Work/aiforweb3/core/mcp/github_server.py"
            server_params = StdioServerParameters(
                command="python",
                args=[server_script_path],
                env=None
            )
            
            try:
                stdio_transport = await self.exit_stack.enter_async_context(
                    stdio_client(server_params)
                )
                self.stdio, self.write = stdio_transport
                self.session = await self.exit_stack.enter_async_context(
                    ClientSession(self.stdio, self.write)
                )
                
                await self.session.initialize()
                
                # 列出可用工具
                response = await self.session.list_tools()
                tools = response.tools
                print(f"✅ [MCP GitHub客户端] 连接成功，可用工具: {[tool.name for tool in tools]}")
                self.is_connected = True
                
            except Exception as e:
                print(f"❌ [MCP GitHub客户端] 启动服务器失败: {str(e)}")
                self.is_connected = False
                raise
    
    async def _ensure_connected(self):
        """确保MCP服务器连接"""
        if not self.is_connected:
            await self._start_mcp_server()
    
    async def search(self, query: str) -> List[SearchResult]:
        """搜索GitHub内容"""
        print(f"🔍 [MCP GitHub客户端] 开始搜索: '{query}'")
        
        # 检查缓存
        cached_results = self.cache.get("mcp_github", query)
        if cached_results:
            print(f"📋 [MCP GitHub客户端] 从缓存获取结果: {len(cached_results)} 条")
            return cached_results
        
        try:
            await self._ensure_connected()
            
            results = []
            
            # 1. 搜索仓库
            print("🔍 [MCP GitHub客户端] 搜索仓库...")
            repo_result = await self.session.call_tool(
                "search_repositories", 
                {"query": query, "per_page": 5}
            )
            
            if repo_result.content and isinstance(repo_result.content, list):
                for content_item in repo_result.content:
                    if hasattr(content_item, 'text'):
                        try:
                            repo_data = json.loads(content_item.text)
                            if "repositories" in repo_data:
                                for repo in repo_data["repositories"]:
                                    results.append(SearchResult(
                                        title=f"📦 {repo['full_name']}",
                                        content=f"{repo['description']}\n⭐ {repo['stars']} stars, 🍴 {repo['forks']} forks\n语言: {repo['language'] or 'Unknown'}",
                                        url=repo['url'],
                                        source="github",
                                        relevance_score=self._calculate_repo_relevance(repo, query),
                                        metadata={
                                            "type": "repository",
                                            "stars": repo['stars'],
                                            "language": repo['language']
                                        }
                                    ))
                        except json.JSONDecodeError:
                            continue
            
            # 2. 搜索代码
            print("🔍 [MCP GitHub客户端] 搜索代码...")
            code_result = await self.session.call_tool(
                "search_code", 
                {"query": query, "per_page": 5}
            )
            
            if code_result.content and isinstance(code_result.content, list):
                for content_item in code_result.content:
                    if hasattr(content_item, 'text'):
                        try:
                            code_data = json.loads(content_item.text)
                            if "code_files" in code_data:
                                for code_file in code_data["code_files"]:
                                    results.append(SearchResult(
                                        title=f"📄 {code_file['name']} ({code_file['repository']})",
                                        content=f"路径: {code_file['path']}\n\n代码片段:\n{code_file['content_snippet']}",
                                        url=code_file['url'],
                                        source="github",
                                        relevance_score=self._calculate_code_relevance(code_file, query),
                                        metadata={
                                            "type": "code",
                                            "repository": code_file['repository'],
                                            "path": code_file['path']
                                        }
                                    ))
                        except json.JSONDecodeError:
                            continue
            
            # 3. 搜索Issues
            print("🔍 [MCP GitHub客户端] 搜索Issues...")
            issue_result = await self.session.call_tool(
                "search_issues", 
                {"query": query, "per_page": 5}
            )
            
            if issue_result.content and isinstance(issue_result.content, list):
                for content_item in issue_result.content:
                    if hasattr(content_item, 'text'):
                        try:
                            issue_data = json.loads(content_item.text)
                            if "issues" in issue_data:
                                for issue in issue_data["issues"]:
                                    results.append(SearchResult(
                                        title=f"🐛 #{issue['number']}: {issue['title']}",
                                        content=f"状态: {issue['state']}\n仓库: {issue['repository']}\n\n{issue['body']}",
                                        url=issue['url'],
                                        source="github",
                                        relevance_score=self._calculate_issue_relevance(issue, query),
                                        metadata={
                                            "type": "issue",
                                            "number": issue['number'],
                                            "state": issue['state'],
                                            "repository": issue['repository']
                                        }
                                    ))
                        except json.JSONDecodeError:
                            continue
            
            # 按相关性排序
            results.sort(key=lambda x: x.relevance_score, reverse=True)
            
            # 限制结果数量
            results = results[:self.max_results]
            
            print(f"✅ [MCP GitHub客户端] 搜索完成，找到 {len(results)} 条结果")
            
            # 缓存结果
            self.cache.set("mcp_github", query, results)
            
            return results
            
        except Exception as e:
            print(f"❌ [MCP GitHub客户端] 搜索失败: {str(e)}")
            return []
    
    def _calculate_repo_relevance(self, repo: Dict, query: str) -> float:
        """计算仓库相关性"""
        score = 0.0
        query_lower = query.lower()
        
        # 名称匹配
        if query_lower in repo['name'].lower():
            score += 0.4
        if query_lower in repo['full_name'].lower():
            score += 0.3
        
        # 描述匹配
        if repo['description'] and query_lower in repo['description'].lower():
            score += 0.3
        
        # 星数加权
        stars = repo.get('stars', 0)
        if stars > 1000:
            score += 0.2
        elif stars > 100:
            score += 0.1
        
        # 语言匹配
        if repo.get('language') and query_lower in repo['language'].lower():
            score += 0.2
        
        return min(score, 1.0)
    
    def _calculate_code_relevance(self, code_file: Dict, query: str) -> float:
        """计算代码相关性"""
        score = 0.0
        query_lower = query.lower()
        
        # 文件名匹配
        if query_lower in code_file['name'].lower():
            score += 0.3
        
        # 路径匹配
        if query_lower in code_file['path'].lower():
            score += 0.2
        
        # 内容匹配
        if code_file.get('content_snippet') and query_lower in code_file['content_snippet'].lower():
            score += 0.5
        
        return min(score, 1.0)
    
    def _calculate_issue_relevance(self, issue: Dict, query: str) -> float:
        """计算Issue相关性"""
        score = 0.0
        query_lower = query.lower()
        
        # 标题匹配
        if query_lower in issue['title'].lower():
            score += 0.4
        
        # 内容匹配
        if issue.get('body') and query_lower in issue['body'].lower():
            score += 0.3
        
        # 状态加权（开放的Issue更相关）
        if issue.get('state') == 'open':
            score += 0.1
        
        # 评论数加权
        comments = issue.get('comments', 0)
        if comments > 10:
            score += 0.1
        elif comments > 5:
            score += 0.05
        
        return min(score, 1.0)
    
    async def cleanup(self):
        """清理资源"""
        try:
            if self.exit_stack:
                await self.exit_stack.aclose()
            if self.server_process:
                self.server_process.terminate()
                self.server_process = None
            self.is_connected = False
            print("🧹 [MCP GitHub客户端] 资源清理完成")
        except Exception as e:
            print(f"⚠️ [MCP GitHub客户端] 清理资源时出错: {str(e)}")
    
    def __del__(self):
        """析构函数"""
        if self.is_connected:
            try:
                asyncio.create_task(self.cleanup())
            except:
                pass